package org.code.chenwei.day01.create;


import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

/**
 * @BelongsProject: learn-learning-everyday
 * @BelongsPackage: org.chenwei.day01.create
 * @Author: Chen Wei
 * @CreateTime: 2024-01-10  10:08
 * @Description: TODO
 * @Version: 1.0
 */
@SuppressWarnings("all")
@Slf4j
public class CreateThreadDemo {

    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();

        new Thread(new MyRunnable()).start();
    }

    //继承Thread创建线程
    @Test
    public void demo01() {
        MyThread thread = new MyThread();
        thread.start();
    }

    @Test
    //实现Runnable接口创建线程
    public void demo02() {
        new Thread(new MyRunnable()).start();
    }

    @Test
    //根据funtureTask创建线程
    public void demo03() throws ExecutionException, InterruptedException {
        //全写
        FutureTask futureTask01 = new FutureTask(new Callable() {
            @Override
            public Object call() throws Exception {
                return 2;
            }
        });
        //lamda表达式
        FutureTask futureTask02 = new FutureTask(() -> {
            System.out.println("子线程执行中");
            return 2;
        });

        new Thread(futureTask01).start();
        new Thread(futureTask02).start();


        Object res01 = futureTask01.get();
        Object res02 = futureTask02.get();
        System.out.println(res01);
        System.out.println(res02);
    }


    //探讨start与run的不同
    //结论
    @Test
    public void startAndRun() {
        Thread runnableThread = new Thread((() -> {
            log.info("4");
        }));
        log.info("1");
        log.info("3");

        runnableThread.start();
        log.info("5");
        log.info("6");


    }

    //yield线程让步
    @Test
    public void yieldThreadDemo() throws InterruptedException {
        class Task implements Runnable {
            @Override
            public void run() {
                for (int i = 0; i < 200; i++) {
                    System.out.println("A:" + i);
                }
            }
        }

        class Task02 implements Runnable {
            @Override
            public void run() {
                for (int i = 0; i < 200; i++) {
                    Thread.yield();
                    System.out.println("B:" + i);
                }
            }
        }
        Thread thread02 = new Thread(new Task02());
        thread02.start();
        thread02.setPriority(Thread.MIN_PRIORITY);
        Thread thread01 = new Thread(new Task());
        thread01.setPriority(Thread.MAX_PRIORITY);
        thread01.start();


        TimeUnit.SECONDS.sleep(5);
    }

    //interrupt 打断线程
    //interrupted 返回打断标记，撤销打断操作
    //isInterrupted 返回打断标记，不撤销打断操作
    @Test
    public void interuptThreadDemo() throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {

                boolean interrupted = Thread.interrupted();
                log.info("线程是否被打断:{}", interrupted);
                if (interrupted) {
                    log.info("线程已经撤销打断");
                }
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            System.out.println("线程执行完毕");

        });
        thread.start();
        log.info("打断前:{}", thread.isInterrupted());
        thread.interrupt();

        log.info("打断后:{}", thread.isInterrupted());

        TimeUnit.SECONDS.sleep(5);


    }


    //模拟Spring boot运行tomcat
    @Test
    public void runTomcat() throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {
                log.info("tomcat is running");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                boolean interrupted = Thread.currentThread().isInterrupted();
                log.info("{}", interrupted);
                if (interrupted) {
                    log.info("tomcat is stop");
                    break;
                }


            }
        });

        thread.start();
        thread.interrupt();
        thread.join();
    }

    //join 等待线程执行完毕
    //isAlive 判断现场是否存活
    @Test
    public void joinTestDemo() throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            log.info("执行完毕");
        });
        thread.start();

        boolean alive = thread.isAlive();
        log.info("{}", alive);
        thread.join();

        boolean alive02 = thread.isAlive();
        log.info("{}", alive02);
    }


    //现场状态
    @Test
    public void threadStateTestDemo() throws InterruptedException {
        Thread thread = new Thread(() -> {
            log.info("开始执行");
            log.info("执行结束");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        log.info("{}", thread.getState());
        thread.start();
        log.info("{}", thread.getState());
        thread.join();
        log.info("{}", thread.getState());
    }


    //阻塞
    //计时等待,阻塞
    @Test
    public void blockTestDemo() throws InterruptedException {
        class Table {
            public synchronized void use() {
                System.out.println(Thread.currentThread().getName() + "-使用桌子");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "-就餐结束");

            }
        }

        System.out.println(Thread.currentThread().getName());
        Table table = new Table();
        Thread thread01 = new Thread(() -> {
            table.use();
        }, "线程一号");
        Thread thread02 = new Thread(() -> {
            table.use();
        }, "线程二号");
        thread01.start();

        TimeUnit.MILLISECONDS.sleep(500);
        thread02.start();
        TimeUnit.MILLISECONDS.sleep(500);

        System.out.println(thread01.getState());
        System.out.println(thread02.getState());
    }
}
